package com.topwalk.service.impl;

import com.google.common.util.concurrent.*;
import com.topwalk.service.ThreadService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;

/**
 * @author tangfl
 */
@Slf4j
@Service
public class ThreadServiceImpl implements ThreadService {

    @Override
    public List<String> getAsyncByFuture() {
        List<String> list = new ArrayList<>();
        ExecutorService executor = Executors.newFixedThreadPool(5);
        ListeningExecutorService guavaExecutor = MoreExecutors.listeningDecorator(executor);
        ListenableFuture<String> future1 = guavaExecutor.submit(() -> {
            //step 1
            log.info("执行step 1");
            return "step1 result";
        });
        ListenableFuture<String> future2 = guavaExecutor.submit(() -> {
            //step 2
            log.info("执行step 2");
            return "step2 result";
        });
        ListenableFuture<List<String>> future1And2 = Futures.allAsList(future1, future2);
        Futures.addCallback(future1And2, new FutureCallback<>() {
            @Override
            public void onSuccess(List<String> result) {
                log.info("{}", result);
                list.addAll(result);
                ListenableFuture<String> future3 = guavaExecutor.submit(() -> {
                    log.info("执行step 3");
                    return "step3 result";
                });
                Futures.addCallback(future3, new FutureCallback<>() {

                    @Override
                    public void onSuccess(String result) {
                        log.info(result);
                        list.add(result);
                    }

                    @Override
                    public void onFailure(@Nonnull Throwable throwable) {
                        log.error("error", throwable);
                    }

                }, guavaExecutor);
            }

            @Override
            public void onFailure(@Nonnull Throwable throwable) {
                log.error("error", throwable);
            }

        }, guavaExecutor);
        return list;
    }

    @Override
    public String getAsyncByCompletableFuture() {
        ExecutorService executor = Executors.newFixedThreadPool(5);
        CompletableFuture<String> cf1 = CompletableFuture.supplyAsync(() -> {
            log.info("执行step 1");
            return "step1 result";
        }, executor);
        CompletableFuture<String> cf2 = CompletableFuture.supplyAsync(() -> {
            log.info("执行step 2");
            return "step2 result";
        });
        return cf1.thenCombine(cf2, (result1, result2) -> {
            log.info("{} , {}", result1, result2);
            log.info("执行step 3");
            return "step3 result";
        }).orTimeout(10, TimeUnit.SECONDS).join();
    }

    @Override
    public void testInterrupt() {
        
        try {
            throw new InterruptedException();
        } catch (InterruptedException e) {
            log.error("", e);
            Thread.currentThread().interrupt();
        }
        log.info("这是后面啦啦啦");
    }

    public static void main(String[] args) {
        log.info("线程开始状态1 {}", Thread.currentThread().isInterrupted());
        // 为线程打中断标记
        Thread.currentThread().interrupt();
        // 当前线程状态是否中断，上一行打中断标记后就是true
        log.info("线程打中断标记状态2 {}", Thread.currentThread().isInterrupted());
        //获取线程中断状态true，并清除
        boolean interrupted = Thread.interrupted();
        log.info("中断标记 {}", interrupted);
        // 清除完中断标记，中断状态false
        log.info("线程清除中断标记后状态3 {}", Thread.currentThread().isInterrupted());
        // 线程阻塞；线程中断过，这里就不会阻塞，继续往下执行
        LockSupport.park();
        boolean interrupted2 = Thread.interrupted();
        log.info("继续运行 {}", interrupted2);
    }
    
}
